<!DOCTYPE HTML>
<html lang="en" class="sidebar-visible no-js light">
    <head>
        <!-- Book generated using mdBook -->
        <meta charset="UTF-8">
        <title>Makefile</title>
        
        


        <!-- Custom HTML head -->
        


        <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
        <meta name="description" content="">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <meta name="theme-color" content="#ffffff" />

        
        <link rel="icon" href="../favicon.svg">
        
        
        <link rel="shortcut icon" href="../favicon.png">
        
        <link rel="stylesheet" href="../css/variables.css">
        <link rel="stylesheet" href="../css/general.css">
        <link rel="stylesheet" href="../css/chrome.css">
        
        <link rel="stylesheet" href="../css/print.css" media="print">
        

        <!-- Fonts -->
        <link rel="stylesheet" href="../FontAwesome/css/font-awesome.css">
        
        <link rel="stylesheet" href="../fonts/fonts.css">
        

        <!-- Highlight.js Stylesheets -->
        <link rel="stylesheet" href="../highlight.css">
        <link rel="stylesheet" href="../tomorrow-night.css">
        <link rel="stylesheet" href="../ayu-highlight.css">

        <!-- Custom theme stylesheets -->
        

        
    </head>
    <body>
        <!-- Provide site root to javascript -->
        <script type="text/javascript">
            var path_to_root = "../";
            var default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "navy" : "light";
        </script>

        <!-- Work around some values being stored in localStorage wrapped in quotes -->
        <script type="text/javascript">
            try {
                var theme = localStorage.getItem('mdbook-theme');
                var sidebar = localStorage.getItem('mdbook-sidebar');

                if (theme.startsWith('"') && theme.endsWith('"')) {
                    localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
                }

                if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
                    localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
                }
            } catch (e) { }
        </script>

        <!-- Set the theme before any content is loaded, prevents flash -->
        <script type="text/javascript">
            var theme;
            try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
            if (theme === null || theme === undefined) { theme = default_theme; }
            var html = document.querySelector('html');
            html.classList.remove('no-js')
            html.classList.remove('light')
            html.classList.add(theme);
            html.classList.add('js');
        </script>

        <!-- Hide / unhide sidebar before it is displayed -->
        <script type="text/javascript">
            var html = document.querySelector('html');
            var sidebar = 'hidden';
            if (document.body.clientWidth >= 1080) {
                try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
                sidebar = sidebar || 'visible';
            }
            html.classList.remove('sidebar-visible');
            html.classList.add("sidebar-" + sidebar);
        </script>

        <nav id="sidebar" class="sidebar" aria-label="Table of contents">
            <div class="sidebar-scrollbox">
                <ol class="chapter"><li class="chapter-item expanded affix "><a href="../目录.html">目录</a></li><li class="chapter-item expanded "><a href="../如何阅读代码.html"><strong aria-hidden="true">1.</strong> 如何阅读代码</a></li><li class="chapter-item expanded "><a href="../应该知道的Linux技巧.html"><strong aria-hidden="true">2.</strong> 应该知道的Linux技巧</a></li><li class="chapter-item expanded "><a href="../bash/index.html"><strong aria-hidden="true">3.</strong> bash</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../bash/8个实用而有趣Bash命令提示行.html"><strong aria-hidden="true">3.1.</strong> 8个实用而有趣Bash命令提示行</a></li><li class="chapter-item expanded "><a href="../bash/Jobs.html"><strong aria-hidden="true">3.2.</strong> Jobs</a></li><li class="chapter-item expanded "><a href="../bash/ShellScript语法一.html"><strong aria-hidden="true">3.3.</strong> ShellScript语法一</a></li><li class="chapter-item expanded "><a href="../bash/ShellScript语法二.html"><strong aria-hidden="true">3.4.</strong> ShellScript语法二</a></li><li class="chapter-item expanded "><a href="../bash/argument_parameter_option.html"><strong aria-hidden="true">3.5.</strong> argument_parameter_option</a></li><li class="chapter-item expanded "><a href="../bash/如何调试bash脚本.html"><strong aria-hidden="true">3.6.</strong> 如何调试bash脚本</a></li><li class="chapter-item expanded "><a href="../bash/cheat_sheet/index.html"><strong aria-hidden="true">3.7.</strong> cheat_sheet</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../bash/cheat_sheet/sh.html"><strong aria-hidden="true">3.7.1.</strong> sh</a></li></ol></li></ol></li><li class="chapter-item expanded "><a href="../cmd/index.html"><strong aria-hidden="true">4.</strong> cmd</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../cmd/awk.html"><strong aria-hidden="true">4.1.</strong> awk</a></li><li class="chapter-item expanded "><a href="../cmd/nm.html"><strong aria-hidden="true">4.2.</strong> nm</a></li><li class="chapter-item expanded "><a href="../cmd/strace_ltrace.html"><strong aria-hidden="true">4.3.</strong> strace_ltrace</a></li><li class="chapter-item expanded "><a href="../cmd/tcpdump.html"><strong aria-hidden="true">4.4.</strong> tcpdump</a></li><li class="chapter-item expanded "><a href="../cmd/cheat_sheet/index.html"><strong aria-hidden="true">4.5.</strong> cheat_sheet</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../cmd/cheat_sheet/awk.html"><strong aria-hidden="true">4.5.1.</strong> awk</a></li><li class="chapter-item expanded "><a href="../cmd/cheat_sheet/tcpdump.html"><strong aria-hidden="true">4.5.2.</strong> tcpdump</a></li></ol></li></ol></li><li class="chapter-item expanded "><a href="../fileSystem/index.html"><strong aria-hidden="true">5.</strong> fileSystem</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../fileSystem/文件系统.html"><strong aria-hidden="true">5.1.</strong> 文件系统</a></li><li class="chapter-item expanded "><a href="../fileSystem/proc/index.html"><strong aria-hidden="true">5.2.</strong> proc</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../fileSystem/proc/[pid]_fd_socket.html"><strong aria-hidden="true">5.2.1.</strong> [pid]_fd_socket</a></li><li class="chapter-item expanded "><a href="../fileSystem/proc/[pid]_status.html"><strong aria-hidden="true">5.2.2.</strong> [pid]_status</a></li><li class="chapter-item expanded "><a href="../fileSystem/proc/net.html"><strong aria-hidden="true">5.2.3.</strong> net</a></li><li class="chapter-item expanded "><a href="../fileSystem/proc/proc浅谈.html"><strong aria-hidden="true">5.2.4.</strong> proc浅谈</a></li></ol></li></ol></li><li class="chapter-item expanded "><a href="../gcc_gdb/index.html"><strong aria-hidden="true">6.</strong> gcc_gdb</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../gcc_gdb/gdb的基本使用.html"><strong aria-hidden="true">6.1.</strong> gdb的基本使用</a></li></ol></li><li class="chapter-item expanded "><a href="../git/index.html"><strong aria-hidden="true">7.</strong> git</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../git/1_git基本要点.html"><strong aria-hidden="true">7.1.</strong> 1_git基本要点</a></li><li class="chapter-item expanded "><a href="../git/2_git配置.html"><strong aria-hidden="true">7.2.</strong> 2_git配置</a></li><li class="chapter-item expanded "><a href="../git/4_git本地操作.html"><strong aria-hidden="true">7.3.</strong> 4_git本地操作</a></li><li class="chapter-item expanded "><a href="../git/5_gitignore.html"><strong aria-hidden="true">7.4.</strong> 5_gitignore</a></li><li class="chapter-item expanded "><a href="../git/6_git分支操作.html"><strong aria-hidden="true">7.5.</strong> 6_git分支操作</a></li><li class="chapter-item expanded "><a href="../git/7_git远程仓库.html"><strong aria-hidden="true">7.6.</strong> 7_git远程仓库</a></li><li class="chapter-item expanded "><a href="../git/8_git通信协议.html"><strong aria-hidden="true">7.7.</strong> 8_git通信协议</a></li><li class="chapter-item expanded "><a href="../git/9_git服务器搭建.html"><strong aria-hidden="true">7.8.</strong> 9_git服务器搭建</a></li><li class="chapter-item expanded "><a href="../git/diff输出格式.html"><strong aria-hidden="true">7.9.</strong> diff输出格式</a></li><li class="chapter-item expanded "><a href="../git/git使用小技巧.html"><strong aria-hidden="true">7.10.</strong> git使用小技巧</a></li><li class="chapter-item expanded "><a href="../git/git分支.html"><strong aria-hidden="true">7.11.</strong> git分支</a></li><li class="chapter-item expanded "><a href="../git/git提供的工具.html"><strong aria-hidden="true">7.12.</strong> git提供的工具</a></li><li class="chapter-item expanded "><a href="../git/git衍合.html"><strong aria-hidden="true">7.13.</strong> git衍合</a></li><li class="chapter-item expanded "><a href="../git/extend/index.html"><strong aria-hidden="true">7.14.</strong> extend</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../git/extend/git_http请求分析.html"><strong aria-hidden="true">7.14.1.</strong> git_http请求分析</a></li></ol></li></ol></li><li class="chapter-item expanded "><a href="../gpg/index.html"><strong aria-hidden="true">8.</strong> gpg</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../gpg/gpg的简单使用.html"><strong aria-hidden="true">8.1.</strong> gpg的简单使用</a></li></ol></li><li class="chapter-item expanded "><a href="../language/index.html"><strong aria-hidden="true">9.</strong> language</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../language/empty.html"><strong aria-hidden="true">9.1.</strong> empty</a></li><li class="chapter-item expanded "><a href="../language/c_plus_plus/index.html"><strong aria-hidden="true">9.2.</strong> c_plus_plus</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../language/c_plus_plus/4个类型转换关键字.html"><strong aria-hidden="true">9.2.1.</strong> 4个类型转换关键字</a></li><li class="chapter-item expanded "><a href="../language/c_plus_plus/RTTI.html"><strong aria-hidden="true">9.2.2.</strong> RTTI</a></li><li class="chapter-item expanded "><a href="../language/c_plus_plus/const.html"><strong aria-hidden="true">9.2.3.</strong> const</a></li><li class="chapter-item expanded "><a href="../language/c_plus_plus/内存对齐.html"><strong aria-hidden="true">9.2.4.</strong> 内存对齐</a></li><li class="chapter-item expanded "><a href="../language/c_plus_plus/拷贝赋值.html"><strong aria-hidden="true">9.2.5.</strong> 拷贝赋值</a></li><li class="chapter-item expanded "><a href="../language/c_plus_plus/指针.html"><strong aria-hidden="true">9.2.6.</strong> 指针</a></li><li class="chapter-item expanded "><a href="../language/c_plus_plus/构造析构.html"><strong aria-hidden="true">9.2.7.</strong> 构造析构</a></li><li class="chapter-item expanded "><a href="../language/c_plus_plus/私有不可访问吗.html"><strong aria-hidden="true">9.2.8.</strong> 私有不可访问吗</a></li><li class="chapter-item expanded "><a href="../language/c_plus_plus/继承.html"><strong aria-hidden="true">9.2.9.</strong> 继承</a></li><li class="chapter-item expanded "><a href="../language/c_plus_plus/虚函数.html"><strong aria-hidden="true">9.2.10.</strong> 虚函数</a></li><li class="chapter-item expanded "><a href="../language/c_plus_plus/静态库的链接.html"><strong aria-hidden="true">9.2.11.</strong> 静态库的链接</a></li></ol></li><li class="chapter-item expanded "><a href="../language/python/index.html"><strong aria-hidden="true">9.3.</strong> python</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../language/python/optparse的简单使用.html"><strong aria-hidden="true">9.3.1.</strong> optparse的简单使用</a></li></ol></li></ol></li><li class="chapter-item expanded "><a href="../linux编程/index.html"><strong aria-hidden="true">10.</strong> linux编程</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../linux编程/常用开发工具.html"><strong aria-hidden="true">10.1.</strong> 常用开发工具</a></li><li class="chapter-item expanded "><a href="../linux编程/线程.html"><strong aria-hidden="true">10.2.</strong> 线程</a></li><li class="chapter-item expanded "><a href="../linux编程/进程.html"><strong aria-hidden="true">10.3.</strong> 进程</a></li><li class="chapter-item expanded "><a href="../linux编程/fs/index.html"><strong aria-hidden="true">10.4.</strong> fs</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../linux编程/fs/dir.html"><strong aria-hidden="true">10.4.1.</strong> dir</a></li><li class="chapter-item expanded "><a href="../linux编程/fs/file.html"><strong aria-hidden="true">10.4.2.</strong> file</a></li><li class="chapter-item expanded "><a href="../linux编程/fs/getcwd_chdir.html"><strong aria-hidden="true">10.4.3.</strong> getcwd_chdir</a></li><li class="chapter-item expanded "><a href="../linux编程/fs/stat.html"><strong aria-hidden="true">10.4.4.</strong> stat</a></li></ol></li></ol></li><li class="chapter-item expanded "><a href="../make/index.html"><strong aria-hidden="true">11.</strong> make</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../make/Makefile.html" class="active"><strong aria-hidden="true">11.1.</strong> Makefile</a></li></ol></li><li class="chapter-item expanded "><a href="../other/index.html"><strong aria-hidden="true">12.</strong> other</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../other/linux设置代理.html"><strong aria-hidden="true">12.1.</strong> linux设置代理</a></li><li class="chapter-item expanded "><a href="../other/负数的补码怎么得到.html"><strong aria-hidden="true">12.2.</strong> 负数的补码怎么得到</a></li><li class="chapter-item expanded "><a href="../other/缓存/index.html"><strong aria-hidden="true">12.3.</strong> 缓存</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../other/缓存/缓存穿透_击穿_雪崩.html"><strong aria-hidden="true">12.3.1.</strong> 缓存穿透_击穿_雪崩</a></li></ol></li></ol></li><li class="chapter-item expanded "><a href="../reference/index.html"><strong aria-hidden="true">13.</strong> reference</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../reference/MEMORY_ALIGNMENT_ISSUE.html"><strong aria-hidden="true">13.1.</strong> MEMORY_ALIGNMENT_ISSUE</a></li></ol></li><li class="chapter-item expanded "><a href="../small_program/index.html"><strong aria-hidden="true">14.</strong> small_program</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../small_program/程序模块.html"><strong aria-hidden="true">14.1.</strong> 程序模块</a></li></ol></li><li class="chapter-item expanded "><a href="../ssh/index.html"><strong aria-hidden="true">15.</strong> ssh</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../ssh/ssh的高级使用方式.html"><strong aria-hidden="true">15.1.</strong> ssh的高级使用方式</a></li><li class="chapter-item expanded "><a href="../ssh/ssh私钥登录.html"><strong aria-hidden="true">15.2.</strong> ssh私钥登录</a></li></ol></li><li class="chapter-item expanded "><a href="../ubuntu/index.html"><strong aria-hidden="true">16.</strong> ubuntu</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../ubuntu/启动器文件.html"><strong aria-hidden="true">16.1.</strong> 启动器文件</a></li></ol></li><li class="chapter-item expanded "><a href="../x/index.html"><strong aria-hidden="true">17.</strong> x</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../x/Linux下的X是什么.html"><strong aria-hidden="true">17.1.</strong> Linux下的X是什么</a></li><li class="chapter-item expanded "><a href="../x/Win10安装VCXSRV.html"><strong aria-hidden="true">17.2.</strong> Win10安装VCXSRV</a></li><li class="chapter-item expanded "><a href="../x/XApplication配置.html"><strong aria-hidden="true">17.3.</strong> XApplication配置</a></li><li class="chapter-item expanded "><a href="../x/startx与xinit.html"><strong aria-hidden="true">17.4.</strong> startx与xinit</a></li></ol></li><li class="chapter-item expanded "><a href="../技术名词/index.html"><strong aria-hidden="true">18.</strong> 技术名词</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../技术名词/cheat_sheet.html"><strong aria-hidden="true">18.1.</strong> cheat_sheet</a></li></ol></li><li class="chapter-item expanded "><a href="../网络/index.html"><strong aria-hidden="true">19.</strong> 网络</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../网络/linux网络.html"><strong aria-hidden="true">19.1.</strong> linux网络</a></li><li class="chapter-item expanded "><a href="../网络/标准的简单网络服务.html"><strong aria-hidden="true">19.2.</strong> 标准的简单网络服务</a></li><li class="chapter-item expanded "><a href="../网络/计算机网络.html"><strong aria-hidden="true">19.3.</strong> 计算机网络</a></li><li class="chapter-item expanded "><a href="../网络/tcp/index.html"><strong aria-hidden="true">19.4.</strong> tcp</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../网络/tcp/tcpKeepAlive与复位报文.html"><strong aria-hidden="true">19.4.1.</strong> tcpKeepAlive与复位报文</a></li><li class="chapter-item expanded "><a href="../网络/tcp/tcpKeepAlive与应用层keepAlive.html"><strong aria-hidden="true">19.4.2.</strong> tcpKeepAlive与应用层keepAlive</a></li><li class="chapter-item expanded "><a href="../网络/tcp/tcp简介.html"><strong aria-hidden="true">19.4.3.</strong> tcp简介</a></li></ol></li></ol></li><li class="chapter-item expanded "><a href="../装机高手/index.html"><strong aria-hidden="true">20.</strong> 装机高手</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../装机高手/empty.html"><strong aria-hidden="true">20.1.</strong> empty</a></li></ol></li></ol>
            </div>
            <div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
        </nav>

        <div id="page-wrapper" class="page-wrapper">

            <div class="page">
                
                <div id="menu-bar-hover-placeholder"></div>
                <div id="menu-bar" class="menu-bar sticky bordered">
                    <div class="left-buttons">
                        <button id="sidebar-toggle" class="icon-button" type="button" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
                            <i class="fa fa-bars"></i>
                        </button>
                        <button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
                            <i class="fa fa-paint-brush"></i>
                        </button>
                        <ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
                            <li role="none"><button role="menuitem" class="theme" id="light">Light (default)</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
                        </ul>
                        
                        <button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
                            <i class="fa fa-search"></i>
                        </button>
                        
                    </div>

                    <h1 class="menu-title"></h1>

                    <div class="right-buttons">
                        
                        <a href="../print.html" title="Print this book" aria-label="Print this book">
                            <i id="print-button" class="fa fa-print"></i>
                        </a>
                        
                        
                    </div>
                </div>

                
                <div id="search-wrapper" class="hidden">
                    <form id="searchbar-outer" class="searchbar-outer">
                        <input type="search" name="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
                    </form>
                    <div id="searchresults-outer" class="searchresults-outer hidden">
                        <div id="searchresults-header" class="searchresults-header"></div>
                        <ul id="searchresults">
                        </ul>
                    </div>
                </div>
                

                <!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
                <script type="text/javascript">
                    document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
                    document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
                    Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
                        link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
                    });
                </script>

                <div id="content" class="content">
                    <main>
                        <h1 id="makefile----todo"><a class="header" href="#makefile----todo">Makefile -- TODO</a></h1>
<p>更详细的教程参考<a href="https://seisman.github.io/how-to-write-makefile/">跟我一起写Makefile</a>.</p>
<h2 id="简介"><a class="header" href="#简介">简介</a></h2>
<p>在讲述这个makefile之前，还是让我们先来粗略地看一看makefile的规则。</p>
<pre><code>target ... : prerequisites ...
    command
    ...
    ...
</code></pre>
<p>makefile中3个概念：</p>
<ul>
<li><strong>target</strong> 可以是一个object file（目标文件），也可以是一个执行文件，还可以是一个标签（label）。对于标签这种特性，在后续的“伪目标”章节中会有叙述。</li>
<li><strong>prerequisites</strong> 生成该target所依赖的文件和/或target</li>
<li><strong>command</strong> 该target要执行的命令（任意的shell命令）
&gt;prerequisites中如果有一个以上的文件比target文件要新的话，command所定义的命令就会被执行。</li>
</ul>
<h2 id="make的工作方式"><a class="header" href="#make的工作方式">make的工作方式</a></h2>
<p>GNU的make工作时的执行步骤如下：（想来其它的make也是类似）</p>
<ol>
<li>读入所有的Makefile。</li>
<li>读入被include的其它Makefile。</li>
<li>初始化文件中的变量。</li>
<li>推导隐晦规则，并分析所有规则。</li>
<li>为所有的目标文件创建依赖关系链。</li>
<li>根据依赖关系，决定哪些目标要重新生成。</li>
<li>执行生成命令。</li>
</ol>
<p>1-5步为第一个阶段，6-7为第二个阶段。第一个阶段中，如果定义的变量被使用了，那么，make会把其展开在使用的位置。但make并不会完全马上展开，make使用的是懒加载，如果变量出现在依赖关系的规则中，那么仅当这条依赖被决定要使用了，变量才会在其内部展开。</p>
<h2 id="引用其它的makefile"><a class="header" href="#引用其它的makefile">引用其它的Makefile</a></h2>
<p>在Makefile使用 include 关键字可以把别的Makefile包含进来，这很像C语言的 #include ，被包含的文件会原模原样的放在当前文件的包含位置。 include 的语法是：</p>
<pre><code>include &lt;filename&gt;
</code></pre>
<p>filename 可以是当前操作系统Shell的文件模式（可以包含路径和通配符）。</p>
<p>在 include 前面可以有一些空字符，但是绝不能是 Tab 键开始。 include 和 <filename> 可以用一个或多个空格隔开。举个例子，你有这样几个Makefile： a.mk 、 b.mk 、 c.mk ，还有一个文件叫 foo.make ，以及一个变量 $(bar) ，其包含了 e.mk 和 f.mk ，那么，下面的语句：</p>
<pre><code>include foo.make *.mk $(bar)
</code></pre>
<p>等价于：</p>
<pre><code>include foo.make a.mk b.mk c.mk e.mk f.mk
</code></pre>
<p>如果有文件没有找到的话，make会生成一条警告信息，但不会马上出现致命错误。它会继续载入其它的文件，一旦完成makefile的读取，make会再重试这些没有找到，或是不能读取的文件，如果还是不行，make才会出现一条致命信息。如果你想让make不理那些无法读取的文件，而继续执行，你可以在include前加一个减号“-”。如：</p>
<pre><code>-include &lt;filename&gt;
</code></pre>
<h2 id="makefile-书写规则"><a class="header" href="#makefile-书写规则">Makefile 书写规则</a></h2>
<h3 id="使用通配符"><a class="header" href="#使用通配符">使用通配符</a></h3>
<p>如果我们想定义一系列比较类似的文件，我们很自然地就想起使用通配符。make支持三个通配符： * ， ? 和 ~ 。这是和Unix的B-Shell是相同的。</p>
<p>波浪号（ ~ ）字符在文件名中也有比较特殊的用途。如果是 ~/test ，这就表示当前用户的 $HOME 目录下的test目录。而 ~hchen/test 则表示用户hchen的宿主目录下的test 目录。（这些都是Unix下的小知识了，make也支持）而在Windows或是 MS-DOS下，用户没有宿主目录，那么波浪号所指的目录则根据环境变量“HOME”而定。
使用通配符的小case:</p>
<pre><code>objects := $(patsubst %.c,%.o,$(wildcard *.c))
</code></pre>
<h2 id="目标"><a class="header" href="#目标">目标</a></h2>
<h3 id="伪目标"><a class="header" href="#伪目标">伪目标</a></h3>
<p>“伪目标”并不是一个文件，只是一个标签，由于“伪目标”不是文件，所以make无法生成它的依赖关系和决定它是否要执行。我们只有通过显式地指明这个“目标”才能让其生效。当然，“伪目标”的取名不能和文件名重名，不然其就失去了“伪目标”的意义了。</p>
<p>当然，为了避免和文件重名的这种情况，我们可以使用一个特殊的标记“.PHONY”来显式地指明一个目标是“伪目标”，向make说明，不管是否有这个文件，这个目标就是“伪目标”。</p>
<pre><code>.PHONY : clean
</code></pre>
<p>只要有这个声明，不管是否有“clean”文件，要运行“clean”这个目标，只有“make clean”这样。于是整个过程可以这样写：</p>
<pre><code>.PHONY : clean
clean :
    -rm *.o temp
</code></pre>
<h3 id="多目标"><a class="header" href="#多目标">多目标</a></h3>
<p>Makefile的规则中的目标可以不止一个，其支持多目标，有可能我们的多个目标同时依赖于一个文件，并且其生成的命令大体类似。于是我们就能把其合并起来。当然，多个目标的生成规则的执行命令不是同一个，这可能会给我们带来麻烦，不过好在我们可以使用一个自动化变量 $@ （关于自动化变量，将在后面讲述），这个变量表示着目前规则中所有的目标的集合，这样说可能很抽象，还是看一个例子吧。</p>
<pre><code>bigoutput littleoutput : text.g
    generate text.g -$(subst output,,$@) &gt; $@
</code></pre>
<p>上述规则等价于：</p>
<pre><code>bigoutput : text.g
    generate text.g -big &gt; bigoutput
littleoutput : text.g
    generate text.g -little &gt; littleoutput
</code></pre>
<p>其中， <code>-$(subst output,,$@)</code> 中的 $ 表示执行一个Makefile的函数，函数名为subst，后面的为参数。关于函数，将在后面讲述。这里的这个函数是替换字符串的意思， $@ 表示目标的集合，就像一个数组， $@ 依次取出目标，并执于命令。</p>
<h3 id="静态模式"><a class="header" href="#静态模式">静态模式</a></h3>
<p>静态模式可以更加容易地定义多目标的规则，可以让我们的规则变得更加的有弹性和灵活。我们还是先来看一下语法：</p>
<pre><code>&lt;targets ...&gt; : &lt;target-pattern&gt; : &lt;prereq-patterns ...&gt;
    &lt;commands&gt;
    ...
</code></pre>
<p>targets定义了一系列的目标文件，可以有通配符。是目标的一个集合。</p>
<p>target-pattern是指明了targets的模式，也就是的目标集模式。</p>
<p>prereq-patterns是目标的依赖模式，它对target-pattern形成的模式再进行一次依赖目标的定义。</p>
<p>这样描述这三个东西，可能还是没有说清楚，还是举个例子来说明一下吧。如果我们的<target-pattern>定义成 %.o ，意思是我们的<target>;集合中都是以 .o 结尾的，而如果我们的<prereq-patterns>定义成 %.c ，意思是对<target-pattern>所形成的目标集进行二次定义，其计算方法是，取<target-pattern>模式中的 % （也就是去掉了 .o 这个结尾），并为其加上 .c 这个结尾，形成的新集合。</p>
<p>所以，我们的“目标模式”或是“依赖模式”中都应该有 % 这个字符，如果你的文件名中有 % 那么你可以使用反斜杠 \ 进行转义，来标明真实的 % 字符。</p>
<p>看一个例子：</p>
<pre><code>objects = foo.o bar.o

all: $(objects)

$(objects): %.o: %.c
    $(CC) -c $(CFLAGS) $&lt; -o $@
</code></pre>
<p>上面的例子中，指明了我们的目标从$object中获取， %.o 表明要所有以 .o 结尾的目标，也就是 foo.o bar.o ，也就是变量 $object 集合的模式，而依赖模式 %.c 则取模式 %.o 的 % ，也就是 foo bar ，并为其加下 .c 的后缀，于是，我们的依赖目标就是 foo.c bar.c 。而命令中的 $&lt; 和 $@ 则是自动化变量， $&lt; 表示第一个依赖文件， $@ 表示目标集（也就是“foo.o bar.o”）。于是，上面的规则展开后等价于下面的规则：</p>
<pre><code>foo.o : foo.c
    $(CC) -c $(CFLAGS) foo.c -o foo.o
bar.o : bar.c
    $(CC) -c $(CFLAGS) bar.c -o bar.o
</code></pre>
<p>试想，如果我们的 %.o 有几百个，那么我们只要用这种很简单的“静态模式规则”就可以写完一堆规则，实在是太有效率了。“静态模式规则”的用法很灵活，如果用得好，那会是一个很强大的功能。再看一个例子：</p>
<pre><code>files = foo.elc bar.o lose.o

$(filter %.o,$(files)): %.o: %.c
    $(CC) -c $(CFLAGS) $&lt; -o $@
$(filter %.elc,$(files)): %.elc: %.el
    emacs -f batch-byte-compile $&lt;
</code></pre>
<p>$(filter %.o,$(files))表示调用Makefile的filter函数，过滤“$files”集，只要其中模式为“%.o”的内容。其它的内容，我就不用多说了吧。这个例子展示了Makefile中更大的弹性。</p>
<h2 id="使用变量"><a class="header" href="#使用变量">使用变量</a></h2>
<h2 id="隐含规则"><a class="header" href="#隐含规则">隐含规则</a></h2>
<h2 id="使用条件判断"><a class="header" href="#使用条件判断">使用条件判断</a></h2>
<h2 id="使用函数"><a class="header" href="#使用函数">使用函数</a></h2>

                    </main>

                    <nav class="nav-wrapper" aria-label="Page navigation">
                        <!-- Mobile navigation buttons -->
                        
                            <a rel="prev" href="../make/index.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
                                <i class="fa fa-angle-left"></i>
                            </a>
                        

                        
                            <a rel="next" href="../other/index.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
                                <i class="fa fa-angle-right"></i>
                            </a>
                        

                        <div style="clear: both"></div>
                    </nav>
                </div>
            </div>

            <nav class="nav-wide-wrapper" aria-label="Page navigation">
                
                    <a rel="prev" href="../make/index.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
                        <i class="fa fa-angle-left"></i>
                    </a>
                

                
                    <a rel="next" href="../other/index.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
                        <i class="fa fa-angle-right"></i>
                    </a>
                
            </nav>

        </div>

        
        <!-- Livereload script (if served using the cli tool) -->
        <script type="text/javascript">
            var socket = new WebSocket("ws://localhost:3000/__livereload");
            socket.onmessage = function (event) {
                if (event.data === "reload") {
                    socket.close();
                    location.reload();
                }
            };

            window.onbeforeunload = function() {
                socket.close();
            }
        </script>
        

        

        

        
        <script type="text/javascript">
            window.playground_copyable = true;
        </script>
        

        

        
        <script src="../elasticlunr.min.js" type="text/javascript" charset="utf-8"></script>
        <script src="../mark.min.js" type="text/javascript" charset="utf-8"></script>
        <script src="../searcher.js" type="text/javascript" charset="utf-8"></script>
        

        <script src="../clipboard.min.js" type="text/javascript" charset="utf-8"></script>
        <script src="../highlight.js" type="text/javascript" charset="utf-8"></script>
        <script src="../book.js" type="text/javascript" charset="utf-8"></script>

        <!-- Custom JS scripts -->
        

        

    </body>
</html>
